perm filename CLIP[TIM,LSP] blob sn#577514 filedate 1981-04-02 generic text, type T, neo UTF8
;;;-*-lisp-*-

;;; The GJC lisp benchmarks.

;; This benchmark tests raw structure referencing, function calling,
;; dispatching, and arithmetic speed. Tail recursion optimization
;; and good register allocation are also applicable.

;; A CLIPPER does line-clipping by a half-plane, they may be 
;; cascaded to clip for arbitrary convex windows.
;; The equation of the half plane is  A*X+B*Y<C
;; If the line is given by the two point formula

;;			  Y2 - Y1   Y1 - Y
;;              	  ------- = ------
;;			  X2 - X1   X1 - X

;; And the edge of the half plane by

;;         		   B Y + A X = C

;; Then the intercept is

;;	   B (X1 Y2 - X2 Y1) + C (X2 - X1)      A (X2 Y1 - X1 Y2) + C (Y2 - Y1)
;;     X = -------------------------------  Y = -------------------------------
;;	      B (Y2 - Y1) + A (X2 - X1)		   B (Y2 - Y1) + A (X2 - X1)

#.(PROGN #+Maclisp (sstatus feature numdcl)
	 #+Maclisp (sstatus feature subrcall)
	 #+Lispm   (sstatus feature arithcheck)
	 nil)

#+numdcl
(DECLARE (FLONUM (DIST FLONUM FLONUM FLONUM FLONUM)
		 (DET FLONUM FLONUM FLONUM FLONUM)
		 #+arithcheck (C-QUOTIENT-INTERNAL FLONUM FLONUM)
		 (X-INTERCEPT-N FLONUM FLONUM FLONUM FLONUM FLONUM)))

(DEFUN DIST (A X B Y) (PLUS (TIMES A X) (TIMES B Y)))
(DEFUN DET (X1 Y1 X2 Y2) (DIFFERENCE (TIMES X1 Y2) (TIMES X2 Y1)))

(DEFUN X-INTERCEPT-N (X1 X2 DET B C)
       (PLUS (TIMES B DET)
	     (TIMES C (DIFFERENCE X2 X1))))

(DEFMACRO X-INTERCEPT (X1 X2 DET B C Q)
	  `(C-QUOTIENT (X-INTERCEPT-N ,X1 ,X2 ,DET ,B ,C) ,Q))

(DEFMACRO Y-INTERCEPT (Y1 Y2 DET A C Q)
	  `(C-QUOTIENT (X-INTERCEPT-N ,Y1 ,Y2 (MINUS ,DET) ,A ,C) ,Q))

(DEFMACRO C-QUOTIENT (X Y)
	  #-arithcheck `(quotient ,x ,y)
	  #+arithcheck `(c-quotient-internal ,x ,y))

#+arithcheck
(progn 'compile
(defvar epsilon 0.00001)
#+numdcl (declare (flonum epsilon))
(defun c-quotient-internal (x y)
       (if (lessp (abs x) epsilon) x (quotient x y)))
)


(DEFVST CLIPPER
	(EXPR #'CLIPPER)
	#+subrcall SUBR
	S
	A
	B
	C)

(DEFMACRO MAKE-CLIPPER (&REST L) `(SETTUP-CLIPPER (CONS-A-CLIPPER ,@L)))

(DEFUN SETTUP-CLIPPER (SELF)
       #+SUBRCALL (SETF (CLIPPER-SUBR SELF)
			(GETSUBR (CLIPPER-EXPR SELF)))
       SELF)

(DEFUN CLIPPER (SELF X1 Y1 X2 Y2)
       #+numdcl (DECLARE (FLONUM  X1 Y1 X2 Y2))
       (LET ((A (CLIPPER-A SELF))
	     (B (CLIPPER-B SELF))
	     (C (CLIPPER-C SELF))
	     (S (CLIPPER-S SELF)))
	    #+numdcl (DECLARE (FLONUM A B C))
	    (LET ((D1 (DIST A X1 B Y1))
		  (D2 (DIST A X2 B Y2)))
		 #+numdcl (DECLARE (FLONUM D1 D2))
		 (COND ((LESSP D1 C)
			(IF (LESSP D2 C)
			    (CLIPPER-CALL S X1 Y1 X2 Y2)
			    (LET ((Q (DIFFERENCE D1 D2))
				  (D (DET X1 Y1 X2 Y2)))
				 #+numdcl (DECLARE (FLONUM Q D))
				 (CLIPPER-CALL
				  S X1 Y1
				  (X-INTERCEPT X1 X2 D B C Q)
				  (Y-INTERCEPT Y1 Y2 D A C Q)))))
		       ((LESSP D2 C))
		       (T
			(LET ((Q (DIFFERENCE D1 D2))
			      (D (DET X1 Y1 X2 Y2)))
			     #+numdcl (DECLARE (FLONUM Q D))
			     (CLIPPER-CALL
			      S
			      (X-INTERCEPT X1 X2 D B C Q)
			      (Y-INTERCEPT Y1 Y2 D A C Q)
			      X2 Y2)))))))

(DEFUN DRAW-LINE (IGNORE-SELF IGNORE2 IGNORE3 IGNORE4 IGNORE5) NIL)

(DEFUN CLIPPER-CALL (CLIPPER X1 Y1 X2 Y2)
       #+subrcall
       (subrcall nil (clipper-subr clipper) clipper x1 y1 x2 y2)
       #-subrcall
       (funcall (clipper-expr clipper) clipper x1 y1 x2 y2)
       )
	
#+subrcall
(PROGN 'COMPILE

(DEFUN TRAMP (SELF X1 Y1 X2 Y2)
       (FUNCALL (CLIPPER-EXPR SELF) SELF X1 Y1 X2 Y2))

(DEFVAR GETSUBR T)

(DEFUN GETSUBR (X)
       (OR (AND GETSUBR (ATOM X) (GET X 'SUBR))
	   (GET 'TRAMP 'SUBR)
	   (GETSUBR (ERROR "No Trampoline" 'TRAMP 'WRNG-TYPE-ARG))))
)


;; The actual test.
;; Remember, A*X+B*Y<C, so for horizonal and vertical lines,
;; B=0 Xc<C/A and A=0 Yc<C/B.

#.`',(SETQ ZERO 0.0 ONE 1.0 LOW 0.0 HI 1.0)

(DEFUN MAKE-TEST-CLIPPER ()
       (MAKE-CLIPPER					; Y < HI
	A #.ZERO
	B #.ONE
	C #.HI
	S (MAKE-CLIPPER					; Y > LOW
	   A #.ZERO
	   B (MINUS #.ONE)
	   C #.LOW
	   S (MAKE-CLIPPER				; X < HI
	      A #.ONE
	      B #.ZERO
	      C #.HI
	      S (MAKE-CLIPPER				; X > LOW
		 A (MINUS #.ONE)
		 B #.ZERO
		 C #.LOW
		 S  (MAKE-CLIPPER
		     EXPR #'DRAW-LINE))))))

(DEFVAR CLIPPER (MAKE-TEST-CLIPPER))


(DEFMACRO TIME-DIFFERENCE-NORMALIZE (X Y)
  #+LISPM `(* (// 1000000. 60.) (TIME-DIFFERENCE ,X ,Y))
  #+MACLISP  `(- ,X ,Y)
  #+NIL  `(- ,X ,Y))

(DEFMACRO SYS-RUNTIME ()
  #+LISPM '(TIME)
  #+MACLISP '(RUNTIME)
  #+NIL '(RUNTIME))

(DEFMACRO DEF-TEST-LOOP (NAME . BODY)
	  `(DEFUN (,NAME TEST-LOOP-EXPR #+subrcall TEST-LOOP-SUBR) (N)
		  (DECLARE (FIXNUM N))
		  (DO ((START-TIME (SYS-RUNTIME))
	       (J 1 (1+ J)))
		      ((> J N)
		       (TIME-DIFFERENCE-NORMALIZE (SYS-RUNTIME) START-TIME))
		      (DECLARE (FIXNUM J))
		      ,@BODY)))

#+NUMDCL (DECLARE (FLONUM (TESTPOINT)))

(DEFUN TESTPOINT ()
       (DIFFERENCE (TIMES #.(PLUS ONE ONE ONE)
			  (FLOAT (RANDOM))
			  #.(QUOTIENT 1 (FLOAT (LSH -1 -1))))
		   #.ONE))

(DEF-TEST-LOOP CLIPPER-CALL
	       (CLIPPER-CALL CLIPPER
			     (TESTPOINT)
			     (TESTPOINT)
			     (TESTPOINT)
			     (TESTPOINT)))

(DEF-TEST-LOOP TESTPOINT
	       (TESTPOINT)
	       (TESTPOINT)
	       (TESTPOINT)
	       (TESTPOINT))

(DEFUN TEST-LOOP (NAME N)
       (LET ((TIME (LET ((P (GETL NAME '(TEST-LOOP-EXPR #+subrcall TEST-LOOP-SUBR))))
			(CASEQ (CAR P)
			       ((TEST-LOOP-EXPR)
				(FUNCALL (CADR P) N))
			       #+subrcall
			       ((TEST-LOOP-SUBR)
				(SUBRCALL NIL (CADR P) N))))))
	    (FORMAT MSGFILES
		    "}&}D loops in }D microseconds = }D microseconds per loop}%"
		    N TIME
		    (// TIME N))))

(DEFUN TEST-RUN (NAME END &OPTIONAL (START 1) (STEP 1))
       (FORMAT MSGFILES
	       "}
	       }&Running clip test }S from }D to }D by step }D.}
	       }%----------------------------------------------------------}%"
	       NAME START END STEP)
       (DO ((K START (+ K STEP))
	    (TIME (SYS-RUNTIME)))
	   ((> K END)
	    (FORMAT MSGFILES
		    "}&------------------------------------------}
		    }%End of test, }D microseconds total.}%"
		    (time-difference-normalize (sys-runtime) time)))
	   (test-loop name k)))